package com.gourd.common.rbac.service;

import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.gourd.common.exception.EntityNotFoundException;
import com.gourd.common.rbac.entity.RbacPermission;
import com.gourd.common.rbac.entity.RbacRole;
import com.gourd.common.rbac.entity.RbacUser;
import com.gourd.common.rbac.vo.JwtUser;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author gourd
 */
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private RbacUserService userService;
    @Autowired
    private RbacRoleService rbacRoleService;

    @Autowired
    private RbacPermissionService permissionService;
    @Override
    @Cached(name = "customUserDetailsService.loadUserByUsername",cacheType = CacheType.BOTH)
    public JwtUser loadUserByUsername(String account){
        // 从数据库中取出用户信息
        RbacUser user = userService.getByAccount(account);

        // 判断用户是否存在
        if(user == null) {
            throw new EntityNotFoundException(RbacUser.class, "account", account);
        }
        // 角色code 和 权限code 同时添加到 authorities中,这样 hasRole(),和 hasAuthority 起作用
        Set<String> authorities = new HashSet<>();
        // 添加权限
        List<RbacRole> rbacRoleList = rbacRoleService.findByUserId(user.getId());
        // hasRole()源码里面是通过拼接上前缀 ROLE_进行匹配角色的
        Set<String> roleCodes = rbacRoleList.stream().map(e -> "ROLE_"+e.getCode()).collect(Collectors.toSet());
        if(CollectionUtils.isNotEmpty(roleCodes)){
            authorities.addAll(roleCodes);
            List<Long> roleIds = rbacRoleList.stream().map(e -> e.getId()).collect(Collectors.toList());
            // 得到用户角色的所有角色所有的权限
            List<RbacPermission> permissionList = permissionService.findByRoleIds(roleIds);
            Set<String> permissionCodes = permissionList.stream().map(e -> e.getCode()).collect(Collectors.toSet());
            if(CollectionUtils.isNotEmpty(permissionCodes)){
                authorities.addAll(permissionCodes);
            }
        }
        user.setAuthorities(authorities);
        JwtUser jwtUser = new JwtUser(user);
        // 返回UserDetails实现类
        return jwtUser;
    }
}
